//
// Created by fairy on 2025/4/26 17:37.
//
#ifndef CORE_H
#define CORE_H
/**
 * @note std里的函数最好不要用，会有问题，导致程序运行很奇怪
 *
 *
*/
#include <complex>
#include <cstring>
#include <zq_drivers.h>
#include <zq_bsp.h>
#ifndef __ARM__
extern "C"
{
#include<Dsplib.h>
}
#endif
#include <adapter_aic23.h>
#include <stdio.h>
#include <util.h>

#include "ui.h"

extern short index_adc;
extern volatile uint16_t index_dac;
extern volatile uint16_t temp3;
extern volatile uint16_t temp4;
extern volatile uint16_t key_test;
extern uint16_t dataL, dataR;

#undef FFT_SIZE
#define FFT_SIZE (128)

extern short buf_adc[FFT_SIZE];
extern short buf_dac[FFT_SIZE];
extern short wave_buf[FFT_SIZE];
extern float amplitude[FFT_SIZE / 2 + 1];

const short square_wave[128] = {
    // 每个周期16个点：前8点为128，后8点为0，重复8次
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 1
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 2
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 3
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 4
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 5
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 6
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 7
    8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 0, 0, 0, 0, 0, 0, 0, 0, // 周期 8
};

// const short sine_wave[128]={}

/**
 * @brief 核心逻辑类
 * @note 为了把核心业务逻辑与main分离，定义了这个类，同时为了避免调用开销，只得写在头文件里。
 */
typedef bsp::aic23::Control::receiveDMA<zq::DMA0> aic23_ReceiveDMA;
typedef bsp::aic23::Control::transmitDMA<zq::DMA1> aic23_TransmitDMA;

class Core
{
    static zq::systick::AsyncDelay baseDelay;

public:
    // ==================== 初始化 ====================
    static void init()
    {
        using namespace zq;
        using namespace bsp;
        baseDelay.start(1000);
        led::clearAll();
        Key::init();
        EnableAPLL();
        aic23::Control::init<aic23::Control::SAMPLE_RATE::SR_32K>(false, false);

        for (int i = 0; i < FFT_SIZE; ++i)
        {
            buf_adc[i] = 0;
        }

        // **********************************  接收 ***************************************

        // =============== C接口初始化 [接收] ==================
        // 配置DMA0用于McBSP0接收
        // DMA0::Config cfg;
        // cfg.srcAddrMode = 0;       // 源地址模式：常量地址（McBSP寄存器固定）
        // cfg.dstAddrMode = 1;       // 目标地址模式：后递增（存入数组）
        // cfg.dataSize = 1;          // 16位数据
        // cfg.autoinit = true;       // 自动重新加载
        // // 这两个端口不能设置错误，否则DMA无法正常启动
        // cfg.srcPort = 3;           // 源端口：外设（McBSP）
        // cfg.dstPort = 1;           // 目标端口：0:SARAM（内存） 1:DARAM
        //
        // DMA0::init(cfg);
        // DMA0::enableIT(true);
        //
        // // 启动DMA传输
        // DMA0::start(
        //     dma::detail::info::Event::McBSP0_Receive,   // 同步事件
        //     mcbsp::regs::drr1::REG,                     // McBSP接收寄存器字节地址
        //     reinterpret_cast<uint32_t>(buf_adc),        // 缓冲区字节地址
        //     FFT_SIZE                                    // 元素数量
        // );


        // =============== 新接口初始化 [接收] ==================
        // DMA0::config::baseInit();
        // DMA0::config::srcAddrMode::constant();
        // DMA0::config::dstAddrMode::increase();
        // DMA0::config::dataSize::_16bit();
        // DMA0::config::autoinit::enable();
        // DMA0::config::srcPort::peripheral();
        // DMA0::config::dstPort::dram();
        // DMA0::config::itConfig::block::enable();

        // =============== 预设初始化 [接收] ==================
        // DMA0::config::mode::peripheralToMemory();// 使用预设
        //
        // // 启动DMA传输
        // DMA0::start(
        //     dma::detail::info::Event::McBSP0_Receive,   // 同步事件
        //     mcbsp::regs::drr1::REG,                     // McBSP接收寄存器字节地址
        //     reinterpret_cast<uint32_t>(buf_adc),        // 缓冲区字节地址
        //     FFT_SIZE                                    // 元素数量
        // );

        // =============== 进一步封装 [接收] ==================
        aic23_ReceiveDMA::init();
        aic23_ReceiveDMA::start(buf_adc,FFT_SIZE);


        // **********************************  发送 ***************************************


        // =============== 循环发送初始化 [发送] ==================
        // DMA0::config::mode::memoryToPeripheral(false);
        // DMA0::config::srcPort::dram();
        // DMA0::config::circleLoop::enable();
        // DMA0::config::priority::high();
        //
        // // 启动DMA传输（如果是发送事件，必须让McBSP主动发送数据才能正确触发DMA）
        // DMA0::start(
        //     dma::detail::info::Event::McBSP0_Transmit,   // 同步事件：McBSP发送
        //     reinterpret_cast<uint32_t>(buf_dac),      // 源地址：正弦波表
        //     mcbsp::regs::dxr1::REG,                     // 目标地址：McBSP发送寄存器
        //     FFT_SIZE                           // 元素数量
        // );
        // aic23::Control::write_data(0x00,0x23);

        // 本段代码放在前面那个循环会导致奇怪的问题，让接收用的DMA无法正常运行
        for (int i = 0; i < 128; ++i)
        {
            buf_dac[i] = 19537 * std::sin(2 * 3.1415926 * i / 128);
        }

        // =============== 封装版初始化 [发送] ==================
        aic23_TransmitDMA::init<true,true>();
        aic23_TransmitDMA::start(buf_dac,FFT_SIZE);


        baseDelay.reset();
    }


    // ==================== 事件处理 ====================
    static void handler()
    {
        using namespace zq;
        using namespace bsp;

        //         for (int i = 0; i < FFT_SIZE; ++i)
        //             wave_buf[i] = square_wave[i];
        // #ifndef __ARM__
        //                 rfft(wave_buf,FFT_SIZE,SCALE);
        // #endif
        //         const uint16_t complex_count = FFT_SIZE / 2;
        //         amplitude[0] = std::abs(wave_buf[0]);
        //         amplitude[complex_count] = std::abs(wave_buf[1])<<1;
        //
        //         for (uint16_t i = 1; i < complex_count; ++i)
        //         {
        //             const float real = wave_buf[2 * i]<<1;
        //             const float imag = wave_buf[2 * i + 1]<<1;
        //             amplitude[i] = std::sqrt(real * real + imag * imag);
        //         }

        if (DMA0::getITFlags(DMA0::IT_Flags::blockIE)) {
            led3::toggle();
            aic23_ReceiveDMA::restart();
        }

        if (baseDelay.is_timeout())
        {
           led1::toggle();
        }


        if (Key::getEvent() == Key::Event::SHORT_PRESS)
        {
           led::write(Key::getCode());
            switch (Key::getCode())
            {
                case 1:
                    aic23::Control::set_sample_rate(aic23::Control::SAMPLE_RATE::SR_96K);
                    break;
                case 2:
                    aic23::Control::set_sample_rate(aic23::Control::SAMPLE_RATE::SR_48K);
                    break;
                case 3:
                    aic23::Control::set_sample_rate(aic23::Control::SAMPLE_RATE::SR_32K);
                    break;

                case 4:
                    aic23::Control::set_sample_rate(aic23::Control::SAMPLE_RATE::SR_8_021K);
                default:
                    break;
            }
        }
    }
};





#endif //CORE_H
